# file containing utilities to group the result of filtering

from couchdb_util import viewGetter
import bisect
import json

class DateGroup:
    # a class used to define a date which could be YYYY-MM, YYYY, YYYY-MM-DD
    # it's main purpose is to define an ordering
    def __init__(self, time, date):
        self.time = time
        if self.time=="month":
            self.date = [int(date[0:4]), int(date[5:7])]
        elif self.time=="year":
            self.date = [int(date[0:4])]
        elif self.time=="day":
            self.date = [int(date[0:4]), int(date[5:7]), int(date[8:10])]
        else:
            raise ValueError
        self.counter = 1
    
    def add(self):
        self.counter += 1
        
    def to_jsonable(self):
        # return a dictionary key, value that can be easily used to convert to json 
        s=""
        for i in range(0, len(self.date)):
            s+=str(self.date[i])
            if not (i==len(self.date)-1):
                s+="-"
        return {'key':s, 'value':self.counter}
            
    ############################# Orderings #################################################################################################
    def __lt__(self, other):
        if self.time=="month":
            if int(self.date[0])<int(other.date[0]):
                return True
            elif int(self.date[0])==int(other.date[0]) and int(self.date[1])<int(other.date[1]):
                return True
            else:
                return False
        if self.time=="year":
            if int(self.date[0])<int(other.date[0]):
                return True
            else:
                return False
        if self.time=="day":
            if int(self.date[0])<int(other.date[0]):
                return True
            elif int(self.date[0])==int(other.date[0]) and int(self.date[1])<int(other.date[1]):
                return True
            elif int(self.date[0])==int(other.date[0]) and int(self.date[1])==int(other.date[1]) and int(self.date[2])<int(other.date[2]):
                return True
            else:
                return False
        raise ValueError
        
    def __le__(self, other):
        if self.time=="month":
            if int(self.date[0])<=int(other.date[0]):
                return True
            elif int(self.date[0])==int(other.date[0]) and int(self.date[1])<=int(other.date[1]):
                return True
            else:
                return False
        if self.time=="year":
            if int(self.date[0])<=int(other.date[0]):
                return True
            else:
                return False
        if self.time=="day":
            if int(self.date[0])<=int(other.date[0]):
                return True
            elif int(self.date[0])==int(other.date[0]) and int(self.date[1])<=int(other.date[1]):
                return True
            elif int(self.date[0])==int(other.date[0]) and int(self.date[1])==int(other.date[1]) and int(self.date[2])<=int(other.date[2]):
                return True
            else:
                return False
        raise ValueError
    
    def __eq__(self, other):
        if self.time=="year":
            return int(self.date[0])==int(other.date[0])
        if self.time=="month":
            return int(self.date[0])==int(other.date[0]) and int(self.date[1])==int(other.date[1])
        if self.time=="day":
            return int(self.date[0])==int(other.date[0]) and int(self.date[1])==int(other.date[1]) and int(self.date[2])==int(other.date[2])
            
    def __cmp__(self, other):
        return self.__eq__(other)
    
    def __ne__(self, other):
          return not self.__eq__(other)
      
    def __gt__(self, other):
          return not self.__le__(other)
      
    def __ge__(self, other):
          return not self.__lt__(other)
    ##########################################################################################################################################


def groupList(objList, couchdb_addr, database, time):
    # group the given object list according to the specified time: month, year, day
    grouped_list = []
    for id in objList:
        doc = viewGetter.getDocumentById(couchdb_addr, database, id)
        if doc['doc_type'] == "Issue":
            gdate = DateGroup(time, doc["dateReported"])
        else:
            gdate = DateGroup(time, doc['date'])
        ind = index(grouped_list, gdate)
        if len(grouped_list)==0:
            print ind, gdate.date
            grouped_list.append(gdate)
        elif ind==-1:
            grouped_list.append(gdate)
        else:
            #print "hip",ind, gdate.date
            grouped_list[ind].add()
            
    return [grouped_list[i].to_jsonable() for i in range(len(grouped_list)-1,-1,-1)]
        
def index(a, x):
    # Locate the leftmost value exactly equal to x in the array a using bisect
    #i = bisect.bisect_left(a, x)
    #if i != len(a) and a[i].__eq__(x):
    #    return i
    #return -1
    ind=0
    for i in a:
        if i.__eq__(x):
            return ind
        ind=ind+1
    return -1